#include "Registro.h"

namespace Toolkit
{

Registro::Registro(const TipoSerializacion tSerializacion) :
    Componente(tSerializacion)
{
    this->dato = NULL;
}

Registro::~Registro()
{
}

bool Registro::operator <(const Clave & clave) const
{
    return !(clave < (*dato) || clave == (*dato));
}

bool Registro::operator ==(const Clave & clave) const
{
    return clave == (*dato);
}

void Registro::setDato(Dato *dato)
{
    this->dato = dato;
}

void Registro::serializar(stringstream& s) const
{
    stringstream ssEspecializacion;
    this->especializacionSerializar(ssEspecializacion);

    stringstream ssDato;
    this->dato->serializar(ssDato);

    stringstream ssMetadataYData;
    ssMetadataYData.write(ssEspecializacion.str().c_str(),
            ssEspecializacion.str().size());
    ssMetadataYData.write(ssDato.str().c_str(), ssDato.str().size());

    char tipo = this->getTipo();
    s.write((char*) &tipo, sizeof(char));

    int tamano = ssMetadataYData.str().size();
    s.write((char*) &tamano, sizeof(int));

    s.write(ssMetadataYData.str().c_str(), ssMetadataYData.str().size());
}

void Registro::hidratar(stringstream& s)
{
    char tipo;
    s.read((char *) &tipo, sizeof(char));

    if (getTipo() == tipo)
    {
        int tamano;
        s.read((char *) &tamano, sizeof(int));

        char *pMetaYDatos = new (char[tamano]);//No hace falta tener en cuenta el \0. Se esta usando al char[] como un buffer de bytes
        s.read(pMetaYDatos, tamano);

        stringstream ssMetaYData;
        ssMetaYData.write(pMetaYDatos, tamano); //Copio la informacion del stringstream desde el cual hidrato, y solo trabajo con la parte que me interesa

        this->especializacionHidratar(ssMetaYData);

        if(this->tieneDato()){
        this->dato->hidratar(ssMetaYData);
        }

        delete pMetaYDatos;
    }
}

void Registro::hidratarDato(Dato &dato)
{
    stringstream serializacion;
    this->dato->serializar(serializacion);
    dato.hidratar(serializacion);
}

char Registro::getTipo() const
{
    return 'R';//TODO cambiar por constante o macro del preprocesador
}

bool Registro::tieneDato() const
{
    return (this->dato != NULL);
}

Dato* Registro::getDato() const
{
	return NULL;
}

}
